package com.pokermind.dse.tcp.protocol;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToByteEncoder;
import io.netty.util.CharsetUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * TCP Protocol Encoder - JSON Version
 * 高性能JSON协议编码器，将ProtocolMessage编码为二进制数据
 * 
 * Protocol Format:
 * +----------+----------+------------------+
 * | Protocol | Body     | JSON String      |
 * | ID       | Length   |                  |
 * | (2 bytes)| (4 bytes)| (N bytes UTF-8)  |
 * +----------+----------+------------------+
 * 
 * 性能优化要点:
 * 1. 使用DirectBuffer减少JVM堆内存压力
 * 2. UTF-8编码优化，避免重复转换
 * 3. 批量写入减少系统调用
 * 4. 异常快速失败，避免连锁反应
 * 
 * @author PokerMind Team
 */
public class ProtocolEncoder extends MessageToByteEncoder<ProtocolMessage> {

    private static final Logger logger = LoggerFactory.getLogger(ProtocolEncoder.class);

    @Override
    protected void encode(ChannelHandlerContext ctx, ProtocolMessage msg, ByteBuf out) throws Exception {
        try {
            // 检查消息是否有效
            if (!isValidMessage(msg)) {
                logger.warn("Invalid protocol message, skipping encode: {}", msg);
                return;
            }

            // 获取JSON字符串并转换为UTF-8字节
            String jsonBody = msg.getJsonBody();
            byte[] jsonBytes = jsonBody.getBytes(CharsetUtil.UTF_8);
            int bodyLength = jsonBytes.length;

            // 验证消息体大小
            if (bodyLength > ProtocolConstants.MAX_BODY_SIZE) {
                logger.error("Message body too large: {} bytes, max: {} bytes, protocol: {}", 
                        bodyLength, ProtocolConstants.MAX_BODY_SIZE, msg.getProtocolName());
                throw new IllegalArgumentException("Message body too large: " + bodyLength);
            }

            // 写入协议头
            out.writeShort(msg.getProtocolId());  // 2 bytes
            out.writeInt(bodyLength);             // 4 bytes

            // 写入消息体 (JSON UTF-8 bytes)
            out.writeBytes(jsonBytes);            // N bytes

            if (logger.isDebugEnabled()) {
                logger.debug("Encoded message: protocol={}, bodyLength={}, requestId={}, to={}",
                        msg.getProtocolName(), bodyLength, msg.getRequestId(), 
                        ctx.channel().remoteAddress());
            }

            // 统计信息
            recordEncodingMetrics(msg, bodyLength);

        } catch (Exception e) {
            logger.error("Error encoding protocol message: {}, error: {}", 
                    msg, e.getMessage(), e);
            
            // 编码失败，关闭连接避免数据污染
            ctx.close();
            throw e;
        }
    }

    /**
     * 验证消息是否有效
     */
    private boolean isValidMessage(ProtocolMessage msg) {
        if (msg == null) {
            logger.warn("Protocol message is null");
            return false;
        }
        
        if (msg.getJsonBody() == null || msg.getJsonBody().trim().isEmpty()) {
            logger.warn("Protocol message body is null or empty: {}", msg);
            return false;
        }
        
        if (!ProtocolConstants.isValidProtocol(msg.getProtocolId())) {
            logger.warn("Invalid protocol ID: {}", msg.getProtocolId());
            return false;
        }
        
        if (!msg.isChannelActive()) {
            logger.debug("Channel is not active, skipping encode: {}", msg.getClientId());
            return false;
        }

        // JSON基本格式检查
        String jsonBody = msg.getJsonBody().trim();
        if (!jsonBody.startsWith("{") || !jsonBody.endsWith("}")) {
            logger.warn("Invalid JSON format in message: {}", msg);
            return false;
        }
        
        return true;
    }

    /**
     * 记录编码指标（用于监控）
     */
    private void recordEncodingMetrics(ProtocolMessage msg, int bodyLength) {
        // TODO: 集成Micrometer指标
        // 这里可以记录编码延迟、消息大小分布等指标
        if (logger.isTraceEnabled()) {
            logger.trace("Encoding metrics: protocol={}, bodySize={}, totalSize={}, requestId={}", 
                    msg.getProtocolName(), bodyLength, 
                    ProtocolConstants.HEADER_SIZE + bodyLength, msg.getRequestId());
        }
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        logger.error("Protocol encoder error for {}: {}", 
                ctx.channel().remoteAddress(), cause.getMessage(), cause);
        ctx.close();
    }

    /**
     * 预分配缓冲区大小，提升性能
     */
    @Override
    protected ByteBuf allocateBuffer(ChannelHandlerContext ctx, ProtocolMessage msg, boolean preferDirect) throws Exception {
        // 预估缓冲区大小：协议头 + JSON字节大小
        // 注意：JSON字符串的UTF-8字节长度可能大于字符长度
        int estimatedSize = ProtocolConstants.HEADER_SIZE + (msg.getJsonBody().length() * 3); // 预留UTF-8编码空间
        
        // 限制最大预分配大小，避免内存浪费
        estimatedSize = Math.min(estimatedSize, ProtocolConstants.MAX_BODY_SIZE + ProtocolConstants.HEADER_SIZE);
        
        // 使用DirectBuffer以减少内存拷贝
        if (preferDirect) {
            return ctx.alloc().directBuffer(estimatedSize);
        } else {
            return ctx.alloc().heapBuffer(estimatedSize);
        }
    }

    @Override
    public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
        if (logger.isDebugEnabled()) {
            logger.debug("Protocol encoder added to channel: {}", ctx.channel().remoteAddress());
        }
        super.handlerAdded(ctx);
    }

    @Override
    public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
        if (logger.isDebugEnabled()) {
            logger.debug("Protocol encoder removed from channel: {}", ctx.channel().remoteAddress());
        }
        super.handlerRemoved(ctx);
    }
}
